package xml;

import model.*;

import com.thoughtworks.xstream.converters.*;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class GameLevelConverter implements Converter{

	private static final String ENTITY_XML_TAG = "entity";
	private static final String SPAWNPOINT_XML_TAG = "spawnpoint";
	private static final String Y_COORD_XML_TAG = "y";
	private static final String X_COORD_XML_TAG = "x";
	private static final String PLAYER_START_XML_TAG = "playerStart";
	private static final String MAZE_XML_TAG = "maze";
	private static final String TITLE_XML_TAG = "title";

	@Override
	public void marshal(Object source, HierarchicalStreamWriter writer,
			MarshallingContext context) {
		GameLevel level = (GameLevel)source;
		writer.addAttribute(TITLE_XML_TAG, level.getTitle());
		writer.startNode(MAZE_XML_TAG);
		context.convertAnother(level.getMaze());
		writer.endNode();
		writer.startNode(PLAYER_START_XML_TAG);
		writer.startNode(X_COORD_XML_TAG);
		writer.setValue(((Integer)level.getPlayerStart().getXCoord()).toString());
		writer.endNode();
		writer.startNode(Y_COORD_XML_TAG);
		writer.setValue(((Integer)level.getPlayerStart().getYCoord()).toString());
		writer.endNode();
		writer.endNode();
		for(int i = 0; i < level.getNumSpawnPoints(); i++){
			writer.startNode(SPAWNPOINT_XML_TAG);
			writer.addAttribute(ENTITY_XML_TAG, level.getSpawnPoint(i).getSpawnType().toString());
			writer.startNode(X_COORD_XML_TAG);
			writer.setValue(((Integer)level.getSpawnPoint(i).getSpawnTile().getXCoord()).toString());
			writer.endNode();
			writer.startNode(Y_COORD_XML_TAG);
			writer.setValue(((Integer)level.getSpawnPoint(i).getSpawnTile().getYCoord()).toString());
			writer.endNode();
			writer.endNode();
		}
	}

	@Override
	public Object unmarshal(HierarchicalStreamReader reader,
			UnmarshallingContext context) {
		GameLevel level = new GameLevel();
		//Get the title of the level.
		String title = reader.getAttribute(TITLE_XML_TAG);
		
		//Move down into the maze node and get a maze object
		reader.moveDown();
		Maze maze = (Maze)context.convertAnother(level, Maze.class);
		reader.moveUp();
		
		//Create the level object from the maze and title
		level = new GameLevel(maze, title);
		
		//Generate playerStart 
		reader.moveDown();
		
		reader.moveDown();
		int x = Integer.parseInt(reader.getValue());
		reader.moveUp();
		
		reader.moveDown();
		int y = Integer.parseInt(reader.getValue());
		reader.moveUp();
		
		level.setPlayerStart(maze.getTile(x, y));
		reader.moveUp();
		
		//Generate the rest of the spawn points
		while(reader.hasMoreChildren()){
			reader.moveDown();
			GameEntity spawnType= Enum.valueOf(GameEntity.class, reader.getAttribute(ENTITY_XML_TAG));
			
			reader.moveDown();
			x = Integer.parseInt(reader.getValue());
			reader.moveUp();
			
			reader.moveDown();
			y = Integer.parseInt(reader.getValue());
			reader.moveUp();
			
			reader.moveUp();
			level.addSpawnPoint(maze.getTile(x, y), spawnType);	
		}
		return level;
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean canConvert(Class type) {
		return type.equals(GameLevel.class);
	}

}
